'use strict';
const db = uniCloud.database();
const rooms = db.collection('rooms');
const gameRecords = db.collection('game_records');
const users = db.collection('users');
const appConfig = {
  appid: 'wxf7abe114e4e3be3f',
  secret: '10688d3dd3c4f3414c9d95edc19369d0'
};

// 获取小程序全局唯一后台接口调用凭据
async function getAccessToken() {
  try {
    // 先从数据库查询是否有未过期的token
    const tokenRecord = await db.collection('access_tokens')
      .orderBy('createTime', 'desc')
      .limit(1)
      .get();
    
    if (tokenRecord.data && tokenRecord.data.length > 0) {
      const token = tokenRecord.data[0];
      // token有效期为2小时，这里用1.5小时作为重新获取的阈值
      if (Date.now() - token.createTime < 5400000) {
        return token.access_token;
      }
    }
    
    // 重新获取token
    const result = await uniCloud.httpclient.request(
      `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appConfig.appid}&secret=${appConfig.secret}`,
      {
        dataType: 'json'
      }
    );
    
    if (!result.data.access_token) {
      throw new Error('获取access_token失败');
    }
    
    // 保存新token到数据库
    await db.collection('access_tokens').add({
      access_token: result.data.access_token,
      createTime: Date.now()
    });
    
    return result.data.access_token;
  } catch (error) {
    console.error('获取access_token失败:', error);
    throw error;
  }
}

exports.main = async (event, context) => {
  const { action, data } = event;
  
  switch (action) {
    case 'create':
      return await createRoom(data);
    case 'join':
      return await joinRoom(data);
    case 'getRoom':
      return await getRoom(data);
    case 'getRecords':
      return await getRecords(data);
    case 'addRecord':
      return await addRecord(data);
    case 'settleRoom':
      return await settleRoom(data);
    case 'getSettleData':
      return await getSettleData(data);
    case 'getSettledRooms':
      return await getSettledRooms(data);
    case 'generateQRCode':
      return await generateQRCode(data);
    default:
      return {
        code: -1,
        msg: '未知操作'
      };
  }
};

// 创建房间
async function createRoom(data) {
  const { roomId, ownerOpenId, ownerName,createTime, updateTime, members } = data;
  
  try {
    // 先确保测试用户存在
    const testUserData = {
      openId: 'test_user',
      nickname: '测试用户',
      avatarUrl: '/static/images/user_logo.png',
      score: 0,
      joinTime: new Date().getTime()
    };
    
    // 获取测试用户信息
    let testUser = await users.where({
      openId: 'test_user'
    }).get();
    
    if (testUser.data.length === 0) {
      console.log('测试用户不存在，创建测试用户');
      const result = await users.add(testUserData);
      testUserData._id = result.id;
      testUser = {
        data: [testUserData]
      };
    }
    
    // 检查房间号是否存在
    const existRoom = await rooms.where({
      roomId: roomId
    }).get();
    
    if (existRoom.data.length > 0) {
      return {
        code: -1,
        msg: '房间号已存在'
      };
    }
    // 创建房间时包含创建者和测试用户
    const roomData = {
      roomId,
      ownerOpenId,
      ownerName,
      createTime,
      updateTime,
      status: 0,
      members: [...members, ...testUser.data ]
    };
    const result = await rooms.add(roomData);
    return {
      code: 0,
      msg: '创建成功',
      data: {
        ...roomData,
        _id: result.id
      }
    };
  } catch (e) {
    console.error(e);
    return {
      code: -1,
      msg: '创建失败'
    };
  }
}

// 加入房间
async function joinRoom(data) {
  const { roomId, userInfo } = data;
  
  try {
    const room = await rooms.where({
      roomId: roomId,
      status: 0
    }).get();
    
    if (room.data.length === 0) {
      return {
        code: -1,
        msg: '房间不存在或已结束'
      };
    }
    
    const roomData = room.data[0];
    // 检查是否已在房间中
    const isMember = roomData.members.some(member => member.openId === userInfo.openId);
    if (isMember) {
      return {
        code: 0,
        msg: '已在房间中',
        data: roomData
      };
    }
    
    // 添加新成员
    const newMember = {
      openId: userInfo.openId,
      nickname: userInfo.nickName,
      avatar: userInfo.avatarUrl,
      score: 0,
      joinTime: Date.now()
    };
    
    await rooms.doc(roomData._id).update({
      members: db.command.push([newMember]),
      updateTime: Date.now()
    });
    
    roomData.members.push(newMember);
    
    return {
      code: 0,
      msg: '加入成功',
      data: roomData
    };
  } catch (e) {
    console.error(e);
    return {
      code: -1,
      msg: '加入失败'
    };
  }
}

// 获取房间信息
async function getRoom(data) {
  const { roomId } = data;
  console.log('获取房间信息，roomId:', roomId);
  
  try {
    const result = await rooms.where({
      roomId: roomId,
      status: 0  // 只获取未结算的房间
    }).get();
    
    console.log('查询结果:', result);
    
    if (result.data.length === 0) {
		return {
			code: -1,
			msg: '房间不存在或已结束'
		};
    }
    
    // 获取房间的游戏记录
    const records = await gameRecords
      .where({
        roomId: roomId,
        status: 0
      })
      .orderBy('createTime', 'desc')
      .get();
    
    return {
      code: 0,
      msg: '获取成功',
      data: {
        ...result.data[0],
        records: records.data
      }
    };
  } catch (e) {
    console.error('获取房间信息失败:', e);
    return {
      code: -1,
      msg: '获取房间信息失败'
    };
  }
}

// 获取房间游戏记录
async function getRecords(data) {
  const { roomId, page = 1, pageSize = 20 } = data;
  console.log('获取游戏记录，参数:', data);
  
  try {
    const records = await gameRecords
      .where({
        roomId: roomId,
        status: 0
      })
      .orderBy('createTime', 'desc')
      .skip((page - 1) * pageSize)
      .limit(pageSize)
      .get();
    
    return {
      code: 0,
      data: records.data
    };
  } catch (e) {
    console.error('获取游戏记录失败:', e);
    return {
      code: -1,
      msg: '获取游戏记录失败'
    };
  }
}

// 添加支付记录
async function addRecord(data) {
  const { roomId, payerOpenid, payeeOpenid, amount } = data;
  console.log('添加支付记录，参数:', data);
  
  try {
    // 获取房间信息
    const room = await rooms.where({
      roomId: roomId,
      status: 0
    }).get();
    
    console.log('查询房间结果:', room);
    
    if (room.data.length === 0) {
      return {
        code: -1,
        msg: '房间不存在或已结束'
      };
    }
    
    const roomData = room.data[0];
    
    // 验证支付方和收款方是否在房间中
    const payer = roomData.members.find(m => m.openId === payerOpenid);
    const payee = roomData.members.find(m => m.openId === payeeOpenid);
    
    if (!payer || !payee) {
      console.error('用户不在房间中', {
        payerOpenid,
        payeeOpenid,
        roomMembers: roomData.members.map(m => ({
          openId: m.openId,
          nickname: m.nickname
        }))
      });
      return {
        code: -1,
        msg: payer ? '收款方不在房间中' : '支付方不在房间中'
      };
    }
    
    // 验证金额
    if (isNaN(amount) || amount <= 0) {
      console.error('金额无效:', amount);
      return {
        code: -1,
        msg: '支付金额必须大于0'
      };
    }
    
    // 更新成员积分
    const updatedMembers = roomData.members.map(member => {
      if (member.openId === payerOpenid) {
        console.log('更新支付方积分:', {
          nickname: member.nickname,
          oldScore: member.score,
          newScore: member.score - amount
        });
        return {
          ...member,
          score: member.score - amount
        };
      }
      if (member.openId === payeeOpenid) {
        console.log('更新收款方积分:', {
          nickname: member.nickname,
          oldScore: member.score,
          newScore: member.score + amount
        });
        return {
          ...member,
          score: member.score + amount
        };
      }
      return member;
    });
    
    // 添加支付记录
    const recordData = {
      roomId,
      payerOpenid,
      payerName: payer.nickname,
      payeeOpenid,
      payeeName: payee.nickname,
      amount,
      createTime: Date.now(),
      updateTime: Date.now(),
      status: 0
    };
    
    console.log('准备添加记录:', recordData);
    console.log('准备更新成员:', updatedMembers);
    
    try {
      // 先更新房间成员积分
      await rooms.doc(roomData._id).update({
        members: updatedMembers,
        updateTime: Date.now()
      });
      
      // 再添加支付记录
      const recordResult = await gameRecords.add(recordData);
      
      console.log('更新完成');
      
      return {
        code: 0,
        msg: '支付成功',
        data: {
          members: updatedMembers,
          record: {
            ...recordData,
            _id: recordResult.id
          }
        }
      };
    } catch (e) {
      console.error('支付操作失败:', e);
      
      // 如果积分已更新但记录添加失败，尝试回滚积分
      try {
        const originalMembers = roomData.members;
        await rooms.doc(roomData._id).update({
          members: originalMembers,
          updateTime: Date.now()
        });
        console.log('积分回滚成功');
      } catch (rollbackError) {
        console.error('积分回滚失败:', rollbackError);
      }
      
      return {
        code: -1,
        msg: e.message || '支付失败'
      };
    }
  } catch (e) {
    console.error('支付操作失败:', e);
    
    // 如果积分已更新但记录添加失败，尝试回滚积分
    try {
      const originalMembers = roomData.members;
      await rooms.doc(roomData._id).update({
        members: originalMembers,
        updateTime: Date.now()
      });
      console.log('积分回滚成功');
    } catch (rollbackError) {
      console.error('积分回滚失败:', rollbackError);
    }
    
    throw e;
  }
}

// 结算房间
async function settleRoom(data) {
  const { roomId } = data;
  console.log('结算房间，roomId:', roomId);
  
  try {
    if (!roomId) {
      console.error('缺少房间ID');
      return {
        code: -1,
        msg: '房间ID不能为空'
      };
    }
    
    const room = await rooms.where({
      roomId: roomId,
      status: 0
    }).get();
    
    console.log('查询房间结果:', room);
    
    if (room.data.length === 0) {
      console.error('房间不存在或已结束, roomId:', roomId);
      return {
        code: -1,
        msg: '房间不存在或已结束'
      };
    }
    
    const roomData = room.data[0];
    
    try {
      console.log('开始更新房间状态, roomId:', roomId);
      
      // 更新每个用户的统计信息
      const userUpdates = roomData.members.map(async member => {
        try {
          // 获取用户当前信息
          const userResult = await users.where({
            openId: member.openId
          }).get();
          
          if (userResult.data.length === 0) {
            console.error('用户不存在:', member.openId);
            return;
          }
          
          const user = userResult.data[0];
          const isWin = member.score > 0;
          const isLose = member.score < 0;
          
          // 计算新的统计数据
          const updateData = {
            gamesCount: (user.gamesCount || 0) + 1,
            totalScore: (user.totalScore || 0) + member.score,
            winningCount: user.winningCount || 0,
            losingCount: user.losingCount || 0,
            updateTime: Date.now()
          };
          
          // 更新胜负场次
          if (member.score > 0) {
            updateData.winningCount += 1;
          } else if (member.score < 0) {
            updateData.losingCount += 1;
          }
          
          // 计算胜率
          updateData.winningRate = Math.round(
            (updateData.winningCount / updateData.gamesCount) * 100
          );
          
          console.log('更新用户统计信息:', {
            openId: member.openId,
            nickname: member.nickname,
            oldData: {
              gamesCount: user.gamesCount || 0,
              totalScore: user.totalScore || 0,
              winningCount: user.winningCount || 0,
              losingCount: user.losingCount || 0,
              winningRate: user.winningRate || 0
            },
            newData: updateData,
            scoreChange: member.score,
            result: isWin ? '胜利' : (isLose ? '失败' : '平局')
          });
          
          // 更新用户信息
          await users.doc(user._id).update(updateData);
        } catch (e) {
          console.error('更新用户统计信息失败:', member.openId, e);
          throw e; // 抛出错误以便上层捕获
        }
      });
      
      // 等待所有用户更新完成
      try {
        await Promise.all(userUpdates);
        console.log('所有用户统计信息更新完成');
      } catch (e) {
        console.error('更新用户统计信息时发生错误:', e);
        throw new Error('更新用户统计信息失败');
      }
      
      // 更新房间状态为已结算
      const roomUpdateResult = await rooms.doc(roomData._id).update({
        status: 1,
        settleTime: Date.now(),
        updateTime: Date.now(),
        // 更新成员状态
        members: roomData.members.map(member => ({
          ...member,
          settled: true
        }))
      });
      
      console.log('房间状态更新结果:', roomUpdateResult);
      
      if (roomUpdateResult.updated === 0) {
        throw new Error('房间状态更新失败');
      }
      
      console.log('开始更新游戏记录状态');
      
      // 更新游戏记录状态
      const recordsUpdateResult = await gameRecords.where({
        roomId: roomId,
        status: 0
      }).update({
        status: 1,
        settled: true,
        updateTime: Date.now()
      });
      
      console.log('游戏记录更新结果:', recordsUpdateResult);
      console.log('更新完成');
      
      return {
        code: 0,
        msg: '结算成功',
        data: {
          ...roomData,
          status: 1
        }
      };
    } catch (e) {
      console.error('结算执行失败:', e);
      throw e;
    }
  } catch (e) {
    console.error('结算房间失败, roomId:', roomId, '错误:', e);
    return {
      code: -1,
      msg: e.message || '结算失败'
    };
  }
}

// 获取结算数据
async function getSettleData(data) {
  const { roomId } = data;
  console.log('获取结算数据，roomId:', roomId);
  
  try {
    // 获取房间信息
    const room = await rooms.where({
      roomId: roomId,
      status: 1  // 已结算的房间
    }).get();
    
    if (room.data.length === 0) {
      return {
        code: -1,
        msg: '房间不存在或未结算'
      };
    }
    
    // 获取支付记录
    const records = await gameRecords
      .where({
        roomId: roomId,
        status: 1
      })
      .orderBy('createTime', 'desc')
      .get();
    
    return {
      code: 0,
      msg: '获取成功',
      data: {
        members: room.data[0].members,
        records: records.data
      }
    };
  } catch (e) {
    console.error('获取结算数据失败:', e);
    return {
      code: -1,
      msg: '获取结算数据失败'
    };
  }
}

// 获取已结算的房间列表
async function getSettledRooms(data) {
  const { page = 1, pageSize = 10, openId } = data;
  
  if (!openId) {
    console.error('缺少用户openId');
    return {
      code: -1,
      msg: '参数错误'
    };
  }
  
  try {
    const result = await rooms
      .where({
        status: 1, // 已结算的房间
        'members.openId': openId // 只查询用户参与的房间
      })
      .orderBy('settleTime', 'desc')
      .skip((page - 1) * pageSize)
      .limit(pageSize)
      .get();
    
    console.log('查询结果:', result);
    
    return {
      code: 0,
      data: result.data
    };
  } catch (e) {
    console.error('获取已结算房间失败:', e);
    return {
      code: -1,
      msg: '获取房间列表失败'
    };
  }
}

// 生成小程序码
async function generateQRCode(data) {
  const { roomId } = data;
  console.log('生成小程序码, roomId:', roomId);
  
  if (!roomId) {
    return {
      code: -1,
      msg: '房间ID不能为空'
    };
  }
  
  try {
    // 获取access_token
    const accessToken = await getAccessToken();
    
    // 调用微信接口生成小程序码
    const result = await uniCloud.httpclient.request(
      `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${accessToken}`,
      {
        method: 'POST',
        contentType: 'json',
        data: {
          scene: roomId,
          page: 'pages/room/room',
          check_path: false,
          env_version: 'release'
        },
        responseType: 'arraybuffer'  // 指定返回二进制数据
      }
    );

    // 检查是否返回了错误信息
    try {
      const errorText = Buffer.from(result.data).toString();
      const errorData = JSON.parse(errorText);
      if (errorData.errcode) {
        throw new Error(errorData.errmsg || '生成小程序码失败');
      }
    } catch (parseError) {
      // 解析失败说明返回的是图片数据
      console.log('返回二进制图片数据，长度:', result.data.length);
    }
    
    // 检查返回的内容类型
    const contentType = result.headers['content-type'];
    if (contentType && contentType.includes('image')) {
      // 返回base64图片数据
      const base64Data = Buffer.from(result.data).toString('base64');
      return {
        code: 0,
        msg: '生成成功',
        data: {
          base64: base64Data,
          contentType: contentType
        }
      };
    } else {
      throw new Error('生成小程序码失败：返回的不是图片数据');
    }
  } catch (e) {
    console.error('生成小程序码失败:', e);
    return {
      code: -1,
      msg: e.message || '生成小程序码失败'
    };
  }
} 